import * as Cesium from '@cesiumjs';
import * as utils from "./utils";
import { g3x_defineProperty, g3x_defineReadonly, GUID } from "@g3x/utils";
import { defaultViewerOptions, defaultViewerDefinition, EMPTY_OBJECT } from "./defaults";
import {viewerUtils, tilesetUtils, layersUtils, imageLayerUtils} from "../../viewerUtils";
import { utils as globeUtils } from "../../globe";


class G3vOverviewer {
  /*
   * @param {Object} dom
   * @param {Object} viewerOptions viewers Options
   */
  constructor(viewerOptions, g3v) {
    console.log("G3vOverviewer constructor!")

    const {dom} = viewerOptions

    if(!dom){
      console.error("dom is required!")
    }

    utils.verifyViewerOptions(viewerOptions)

    const viewer = utils.createViewer(dom, viewerOptions, g3v);
    const scene = viewer.scene;
    const globe = scene.globe;

    let _this = this;

    g3x_defineReadonly(this, "viewerOptions", viewerOptions);
    g3x_defineReadonly(this, "guid", viewerOptions.guid);
    g3x_defineReadonly(this, "name", viewerOptions.name);
    g3x_defineProperty(this, "title", viewerOptions.title);
    g3x_defineReadonly(this, "viewer", viewer);
    g3x_defineReadonly(this, "scene", scene);
    g3x_defineReadonly(this, "camera", ()=>{return viewer.camera});
    g3x_defineReadonly(this, "globe", globe);
    g3x_defineReadonly(this, "dataSources", ()=>{return viewer.dataSources});
    g3x_defineReadonly(this, "baseImageLayer", ()=>{return viewer.imageryLayers.get(0)});
    g3x_defineReadonly(this, "imageryLayers", ()=>{return viewer.imageryLayers});
    g3x_defineReadonly(this, "entities", ()=>{return viewer.entities});
    g3x_defineReadonly(this, "primitives", ()=>{return scene.primitives});
    g3x_defineReadonly(this, "groundPrimitives", ()=>{return scene.groundPrimitives});

    Object.defineProperty(this, "layers", {
      get() {
        return new function(){
          this.get = (name)=>{
            return layersUtils.get(viewer,name)
          }
        }
      }
    })

    this.navigation = viewerUtils.initNavigation(viewer, viewerOptions.navigation)

    imageLayerUtils.updateImageLayerByOptions(this.baseImageLayer, viewerOptions.viewer.imagery)
    imageLayerUtils.updateImageLayerTitle(this.baseImageLayer, viewerOptions.viewer.imagery)

    viewerUtils.addlayers(viewer, viewerOptions.layers || []);
    globeUtils.updateGlobeByOptions(globe, viewerOptions.globe);

    (viewerOptions.hideLayers) && imageryLayers._layers.forEach(e => e.show = false);
    viewer.bottomContainer.style.display = (viewerOptions.bottomContainer?"block":"none");

    this.g3vViewers = [];
    this.listeners = {};
    this.marks = {};
  }

  listenerCameraChanged(g3vViewer){
    let _this = this;
    const { camera, scene, guid } = g3vViewer;

    const cartesian = new Cesium.Cartesian2()

    function getCenterPosition(g3vViewer){
      const { clientWidth, clientHeight } = scene.canvas;
      cartesian.x = clientWidth / 2;
      cartesian.y = clientHeight / 2;
      return camera.pickEllipsoid(cartesian);
    }

    return (ev)=>{
      var position = getCenterPosition(g3vViewer);
      var mark = _this.marks[guid];
      if(mark){
        mark.position = position;
        return;
      }
     mark = _this.entities.add({
        position,
        billboard: {
          // 图像地址，URI或Canvas的属性
          image: '//zzgis.com/cdn/3d/g3x/icons/cross-red.png',
          // 设置颜色和透明度
          color: Cesium.Color.WHITE.withAlpha(0.8),
          // 高度（以像素为单位）
          height: 128,
          // 宽度（以像素为单位）
          width: 128,
          // 逆时针旋转
          rotation: 0,
          // 大小是否以米为单位
          sizeInMeters: false,
          // 相对于坐标的垂直位置
          verticalOrigin: Cesium.VerticalOrigin.CENTER,
          // 相对于坐标的水平位置
          horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
          // 该属性指定标签在屏幕空间中距此标签原点的像素偏移量
          // pixelOffset: new Cesium.Cartesian2(0, 0),
          // 应用于图像的统一比例。比例大于会1.0放大标签，而比例小于会1.0缩小标签。
          scale: 0.25,
          // 是否显示
          show: true
        }
      });
      mark.title = g3vViewer.title;
      _this.marks[guid] = mark
    }
  }

  add(g3vViewer){
    let _this = this;
    this.g3vViewers.push(g3vViewer);
    const { camera, guid } = g3vViewer;
    let callback = _this.listenerCameraChanged(g3vViewer);
    const listener = camera.changed.addEventListener(callback, _this);
    this.listeners[guid] = listener;
    callback();
  }

  destroy() {
    let _this = this;
    const {entities} = _this;
    entities.removeAll();
    this.navigation && this.navigation.destroy()
    this.navigation = null;
    this.viewer && this.viewer.destroy()

    this.g3vViewers.forEach((e,i) => {
      e.camera.changed.removeEventListener(_this.listeners[e.guid], _this)
      _this.listeners[e.guid] = null;
    });

    this.marks = {};
    this.g3vViewers = [];
    this.listeners = {};
  }
}

export default G3vOverviewer;
